home *** CD-ROM | disk | FTP | other *** search
- Path: chronicle.mti.sgi.com!austern
- From: rsm@gateway.Dtseng.Com (Roger S. Morris)
- Newsgroups: comp.std.c++
- Subject: Re: Generic Object Callbacks
- Date: 23 Feb 1996 09:45:18 PST
- Organization: Discrete Time Systems Corporation
- Approved: austern@isolde.mti.sgi.com
- Message-ID: <Dn8MAL.Evw@mv.mv.com>
- References: <pgpmoose.199602221531.14635@isolde.mti.sgi.com>
- NNTP-Posting-Host: isolde.mti.sgi.com
- X-Original-Date: Fri, 23 Feb 1996 16:39:57 GMT
- Apparently-To: comp-std-c++@uunet.mv.com
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBVAwUBMS39Uky4NqrwXLNJAQFgVwH7BXtVNrdao2Du46qbMLFJ6oFFWjvVVjBg
- N6J1dyhKl/3wpt9OMGxYmxOYHkO7oDzvxLVZYs3MPQWQ8mQxeE8F5g==
- =QRFD
- Originator: austern@isolde.mti.sgi.com
-
- Hi, We've had to address the same problem.
-
- We've developed a general-purpose callback class that can be used to
- contain almost any kind of callback. This code is "under development"
- in that I'm not convinced that it has the cleanest-possible interface.
- The code works with the latest gnu compiler.
-
- Why do I mention this in comp.std.c++? Well, firstly in order to respond
- to the original poster. Secondly, I'd like to mention that this sort
- of code would be much cleaner if the language had a notion of a
- ``parameter-list'' type, which would allow me to manipulate, store, and
- pass along any list of parameters. Also, it would be nice if a function
- of return type ``void'' would be allowed to return a void. For example,
- void foo() {}
- void bar() { return foo(); }
-
- If anyone is interested in our code, I will place the code at the following
- http address today: http://www.dtseng.com/sig/callback .
- Any comments would be really appreciated.
-
- --Roger Morris
-
-
- Here are some of the comments from callback.H...
-
- /// INTRODUCTION ////////////////////////////////////////////////////////////
- //
- // This file defines a general-purpose "CALLBACK HANDLE", an object that
- // represents everything a caller needs for making a function callback.
- // Here is an example:
- // Suppose that class ``PushButton'' is some sort of graphical widget
- // that performs a callback when "pushed". It's ctor might look like:
- // PushButton::PushButton( string name, Win window, callback0 cb );
- // where ``cb'' represents the function to be called.
- //
- // In order to have a function ``foo1'',
- // void foo1();
- // called by a PushButton ``pb1'', create ``pb1'' as follows:
- // PushButton pb1(name,win, callback0(&foo1) );
- // or simply:
- // PushButton pb1(name,win, &foo1 );
- //
- // In order to have a member function ``foo2'',
- // struct S { void foo2(); } s2;
- // called by a PushButton ``pb2'', create ``pb2'' as follows:
- // PushButton pb2(name,win, callback0_mf<S>(&s2,&s2::foo2) );
- //
- // In order to have a function ``foo3'',
- // void foo3( const bool& );
- // called with ``true'' when ``pbT'' is pushed and with ``false''
- // when ``pbF'' is pushed, create ``pbT'' and ``pbF'' as follows:
- // PushButton pbT(name,win, callback0_tag<bool>(&foo3,true) );
- // PushButton pbF(name,win, callback0_tag<bool>(&foo3,false) );
- //
- // Lastly, suppose that ``PushButton'' actually passes a reference
- // to an ``EventStruct'' to the callback. In this case, its ctor
- // might instead look like:
- // PushButton::PushButton( string, Win, callback1<EventStruct> cb );
- // Though the ctor interface has changed, the code above that initializes
- // ``pb1'', ``pb2'', ``pbT'', and ``pbF'' WILL STILL WORK PERFECTLY FINE
- // as coded (because a callback1<EventStruct> can be constructed from a
- // callback0). It is now possible, however, to have a function ``foo4'',
- // void foo4( EventStruct& );
- // called by a PushButton ``pb4'' by creating ``pb4'' as follows:
- // PushButton pb4(name,win, callback1<EventStruct>(&foo4) );
- // or simply:
- // PushButton pb4(name,win, &foo4 );
- // The purpose of the "callback handle" is to separate the "caller" from
- // the "callee" as much as possible; neither should have to be concerned
- // about the irrelavent (from its point of view) details of the other.
- //
- /// OVERVIEW ////////////////////////////////////////////////////////////////
- //
- // Use of these callback handles allow a function callback to be made without
- // the caller having to know:
- // - Whether the called function is a static (global) function or a member
- // function,
- // - What object the called function is a member of, if any,
- // - What special callee-provided parameters must be passed, such as
- // the ``void* tag'' parameter so-often used with Motif call-back
- // functions.
- // and without the callee having to:
- // - Set up a special static function to wrap each member function in.
- // - Bypass type checking by casting a ``void* tag'' argument.
- // - Point a ``tag'' argument to a special intermediate class just to
- // associate another piece of data with the callback.
- //
- // Other less-important features provided:
- // - The callback handles are implemented as counted-reference handles,
- // and so can be passed around or placed in lists without lots of
- // copy constructor overhead.
- // - The handles are default constructable, copy constructable, and
- // equality comparable. This allows easy use within STL containers.
- // - The actual handle objects contain virtual member functions and a
- // single data element (a pointer), so their size is likely to be
- // only that of a couple of pointers.
- // (Note, once the compiler supports templated member functions, it
- // will be possible to reimplement this without virtual member
- // functions.)
- // - The callee has the ability to invalidate its handles, and so
- // cause an error to be thrown if a callback is attempted.
- //
- // Through use of these handles, a callback can receive up to 3 arguments:
- // - "P1" is caller-provided,
- // -- --
- // - "P2" is caller-provided,
- // -- --
- // - "TAG" is callee-provided (such as Motif's ``void* tag'' param).
- // --- --
- //
- // The callback's RETURN VALUE IS ALWAYS IGNORED.
- //
- // A caller which has parameters to pass will use a ``callback1<P1TYPE>''
- // or a ``callback2<P1TYPE,P2TYPE>'' handle. A caller without
- // arguments will use a ``callback0'' handle.
- //
- // If additional parameters or return data is needed, they must be grouped
- // into P1, P2, or TAG (perhaps with pair<..>). (Alternatively, the user can
- // extend this framework to handle more params or a return value, but things
- // are already complicated enough. Perhaps someday it will be possible in
- // C++ to parameterize parameter lists, not just individual parameters.)
- //
- ---
- [ To submit articles: Try just posting with your newsreader. If that fails,
- use mailto:std-c++@ncar.ucar.edu
- FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html
- Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html
- Comments? mailto:std-c++-request@ncar.ucar.edu
- ]
-